home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / ethrax25 / slipmerg.asm < prev    next >
Assembly Source File  |  1994-05-30  |  48KB  |  1,821 lines

  1. debug equ 1
  2. version    equ    7
  3. axversion equ '940530'
  4.  
  5.     include    defs.asm
  6.   if    ETHERAX25
  7.         include ax25.asm
  8.   endif
  9.  
  10. ;Ported from Phil Karn's asy.c and slip.c, a C-language driver for the IBM-PC
  11. ;8250 by Russell Nelson.  Any bugs are due to Russell Nelson.
  12. ;16550 support ruthlessly stolen from Phil Karn's 8250.c. 
  13. ;  Bugs by Denis DeLaRoca
  14. ;
  15.  if ETHERSLIP
  16. ; Modified by Michael Martineau to provide a class 1 interface.
  17. ; Additional modifications by Joe Doupnik, jrd@cc.usu.edu, 5 Nov 1991
  18. ;  Do not use "c0h" as leading vendor byte in artifical Ethernet address.
  19. ;  Use originator's Ethernet address as destination of ARP Reply address.
  20. ;
  21.  endif
  22.  
  23.  if ETHERAX25
  24. ; Modified by Gary Grebus to produce KISS-encapsulated AX.25 UI frames.
  25. ; Presents a class 1 interface, with AX.25 link layer addresses mapped 
  26. ; to and from pseudo-Ethernet addresses.
  27. ; glg@k8lt.ampr.org    30 May 1994
  28. ;
  29.  endif
  30.  
  31. ; Stopped failures from lost transmit interrupts (by eliminating the ints
  32. ; altogether). Remove unneeded transmitter buffer.
  33. ; Version 6 by Joe Doupnik, jrd@cc.usu.edu, Utah State University, Dec 1991.
  34. ; Fix hardware handshaking problems.  Philip R. "Pib" Burns,
  35. ;   Northwestern University, September, 1992.
  36.  
  37. ;  Copyright, 1988, 1991, Russell Nelson
  38.  
  39. ;   This program is free software; you can redistribute it and/or modify
  40. ;   it under the terms of the GNU General Public License as published by
  41. ;   the Free Software Foundation, version 1.
  42. ;
  43. ;   This program is distributed in the hope that it will be useful,
  44. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  45. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  46. ;   GNU General Public License for more details.
  47. ;
  48. ;   You should have received a copy of the GNU General Public License
  49. ;   along with this program; if not, write to the Free Software
  50. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  51.  
  52. code    segment    word public
  53.     assume    cs:code, ds:code
  54.  
  55.     include    8250defs.asm
  56.  
  57. ;Slip Definitions
  58. FR_END        equ    0c0h        ;Frame End
  59. FR_ESC        equ    0dbh        ;Frame Escape
  60. T_FR_END    equ    0dch        ;Transposed frame end
  61. T_FR_ESC    equ    0ddh        ;Transposed frame escape
  62.  
  63.     public    int_no
  64. int_no        db    4,0,0,0        ; interrupt number.
  65. io_addr        dw    03f8h,0        ; I/O address for COM1
  66. baud_rate    dw    12c0h,0        ; support baud higher than 65535
  67. baudclk        label    word
  68.         dd    115200        ; 1.8432 Mhz / 16
  69. hardware_switch    db    0        ; if zero, don't use hw handshaking
  70. is_16550        db      0               ; 0=no, 1=yes (try using fifo)
  71.  
  72.     public    driver_class, driver_type, driver_name 
  73.     public    driver_function, parameter_list
  74.   if    ETHERSLIP
  75. driver_class    db    1,0,0,0        ;from the packet spec
  76. driver_type    db    0,0,0,0        ;from the packet spec
  77. driver_name    db    'ETHERSLIP',0    ;name of the driver.
  78.   else
  79.     if     ETHERAX25
  80. driver_class    db    1,0,0,0        ;from the packet spec
  81. driver_type    db    0,0,0,0        ;from the packet spec
  82. driver_name    db    'ETHERSLIP',0    ;name of the driver.
  83.     else
  84. driver_class    db    6,0,0,0        ;from the packet spec
  85. driver_type    db    0,0,0,0        ;from the packet spec
  86. driver_name    db    'SLIP8250',0    ;name of the driver.
  87.     endif
  88.   endif
  89.  
  90. driver_function    db    2
  91. parameter_list    label    byte
  92.     db    1            ;major rev of packet driver
  93.     db    9            ;minor rev of packet driver
  94.     db    14            ;length of parameter list
  95.     db    EADDR_LEN        ;length of MAC-layer address
  96.     dw    GIANT            ;MTU, including MAC headers
  97.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  98.     dw    0            ;(# of back-to-back MTU rcvs) - 1
  99.     dw    0            ;(# of successive xmits) - 1
  100. int_num    dw    0            ;Interrupt # to hook for post-EOI
  101.                     ;processing, 0 == none,
  102.  
  103.   ifdef debug
  104.     public recv_buf_size, recv_buf,    recv_buf_end, recv_buf_head
  105.     public recv_buf_tail, recv_pkt_ready
  106.   endif
  107. recv_buf_size    dw    3000,0        ;receive buffer size
  108. recv_buf    dw    ?        ;->receive buffer
  109. recv_buf_end    dw    ?        ;->after end of buffer
  110. recv_buf_head    dw    ?        ;->next character to get
  111. recv_buf_tail    dw    ?        ;->next character to store
  112. recv_pkt_ready    dw    0        ; flag indicating a packet is ready
  113.  
  114.   ifdef debug
  115.     public packet_sem, xmit_time
  116.   endif
  117. packet_sem    dw    0        ; semaphore for    packets received
  118. asyrxint_cnt    dw    0        ; loop counter in asyrxint
  119. xmit_time    dw    0        ; loop timer for asyrxint
  120.  
  121.   if    ETHERSLIP
  122. ;
  123. ; Ethernet format ARP request/reply packet structure.
  124. ;
  125. arp        struc 
  126. arp_hw        dw ?         ; Hardware address length, bytes 
  127. arp_prot    dw ?         ; Protocol type 
  128. arp_hwalen    db ?         ; hardware address length, bytes 
  129. arp_pralen     db ?         ; Length of protocol address 
  130. arp_opcode      dw ?         ; ARP opcode (request/reply) 
  131. arp_shwaddr    db 6 dup(?)    ; Sender hardware address field 
  132. arp_sprotaddr    dd ?        ; Sender Protocol address field 
  133. arp_thwaddr    db 6 dup(?)    ; Target hardware address field 
  134. arp_tprotaddr    dd ?        ; Target protocol address field 
  135. arp        ends
  136.  
  137.   endif
  138.  
  139.   if ETHERSLIP OR ETHERAX25
  140. ;
  141. ; recv_find() requires a pointer to the Ethernet packet type.  Since
  142. ; the incoming packet does not contain an Ethernet packet type field,
  143. ; memory must be allocated to hold the Ethernet packet type.  Space is
  144. ; required for both IP and ARP types.
  145. ;
  146. ip_type label word
  147.         db    08h
  148.         db    00h
  149.  
  150. arp_type label word
  151.         db    08h
  152.         db    06h
  153.   endif
  154.  
  155.   if  ETHERAX25
  156. ;
  157. ; Buffer to hold an ARP packet with link addresses in AX.25 form
  158. a_arp    label    byte
  159.     dw    0300h            ; Hardware addr type - AX.25
  160.     dw    0cc00h            ; Protocol type - IP
  161.     db    07            ; HW address length
  162.     db    04            ; Protocol address length
  163.     dw    ?            ; Space for the ARP opcode
  164.     db    7 dup (?)        ; Space for sender HW addr
  165.     db    4 dup (?)        ; Space for sender protocol addr
  166.     db    7 dup (?)        ; Space for target HW addr
  167.     db    4 dup (?)        ; Space for target protocol addr
  168. A_ARP_LEN    equ    $ - a_arp
  169. ;
  170. ; Current AX.25 callsign in shifted form.  Matches the Pseudo-ethernet
  171. ; address in my_addr.
  172. ; One copy formatted for transmitting.
  173. my_ax25 label   byte
  174.         db      "N" SHL 1
  175.         db      "O" SHL 1
  176.         db      "C" SHL 1
  177.         db      "A" SHL 1
  178.         db      "L" SHL 1
  179.         db      "L" SHL 1
  180.         db      E or RSRVD
  181.  
  182. ; One copy to compare against received packet
  183. my_ax25_rx label   byte
  184.         db      "N" SHL 1
  185.         db      "O" SHL 1
  186.         db      "C" SHL 1
  187.         db      "A" SHL 1
  188.         db      "L" SHL 1
  189.         db      "L" SHL 1
  190.         db      0
  191. ;
  192. ; Buffer for destination AX.25 address
  193. ;
  194. ax25desta  db      AXALEN DUP (?)
  195. ;
  196. ; Buffer to hold header portion of an incoming KISS/AX.25 frame as it is
  197. ; being un-slipped.
  198. ax25header     label    byte
  199. ax25_kiss     db    ?        ; KISS packet type
  200. ax25_dst    db    7 dup (?)     ; Destination address
  201. ax25_src    db    7 dup (?)     ; Source address
  202. ax25_control    db    ?        ; Control field
  203. ax25_pid    db    ?        ; Protocol id
  204. AX25_HDR_LEN    equ    $ - ax25header
  205.  
  206.     public    ax25_stat_in, ax25_stat_ours, ax25_stat_unsup, ax25_stat_bad
  207. ax25_stat_in    dw    ?,?        ; AX.25 packets processed
  208. ax25_stat_bad    dw    ?,?        ; AX.25 packets with an error
  209. ax25_stat_ours    dw    ?,?        ; AX.25 packets to our address
  210. ax25_stat_unsup    dw    ?,?        ; AX.25 packets using unsupported
  211.                     ; features (digis, connected, etc)
  212.  
  213.         extrn   _EtherToAX25: near
  214.     extrn    _AX25ToEther: near
  215.     extrn    _AArpToEArp: near
  216.     extrn    _EArpToAArp: near
  217.   else
  218.  
  219. ; Pseudo-Ethernet address to return in the ARP reply packet.
  220. your_addr    label     byte
  221.         db    00
  222.         db    00
  223.         db    0
  224.         db    22h
  225.         db    34h
  226.         db    66h
  227.  
  228.   endif
  229.  
  230. raw_mode    db    0        ;=1 if we send and receive raw chars.
  231.  
  232.     public    rcv_modes
  233. rcv_modes    dw    8        ;number    of receive modes in our table
  234.   if ETHERAX25
  235.         dw    0,0,0,rcv_mode_3  ; 
  236.         dw    0,0,rcv_mode_6,rcv_mode_7
  237.   else
  238.         dw    0,0,0,rcv_mode_3  ; 
  239.         dw    0,0,0,rcv_mode_7
  240.   endif
  241.  
  242.  
  243.     public bad_command_intercept
  244. bad_command_intercept:
  245. ;called with ah=command, unknown to the skeleton.
  246. ;exit with nc if okay, cy, dh=error if not.
  247.     mov    dh,BAD_COMMAND
  248.     stc
  249.     ret
  250.  
  251.     public    as_send_pkt
  252. ; The Asynchronous Transmit Packet routine.
  253. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  254. ;   interrupts possibly enabled.
  255. ; Exit with nc if ok, or else cy if error, dh set to error number.
  256. ;   es:di and interrupt enable flag preserved on exit.
  257. as_send_pkt:
  258.     ret
  259.  
  260.     public    drop_pkt
  261. ; Drop a packet from the queue.
  262. ; Enter with es:di -> iocb.
  263. drop_pkt:
  264.     assume    ds:nothing
  265.     ret
  266.  
  267.     public    xmit
  268. ; Process a transmit interrupt with the least possible latency to achieve
  269. ;   back-to-back packet transmissions.
  270. ; May only use ax and dx.
  271. xmit:
  272.     assume    ds:nothing
  273.     ret
  274.  
  275.  
  276.     public    send_pkt
  277. ;
  278. ; mod 7/25/89 John Grover
  279. ; - operates with interrupts on. Xmits one byte per interrupt
  280. ; - only turns transmitter buffer empty interrupt off when
  281. ; - all bytes of all packets are transmitted.
  282.  
  283. send_pkt:
  284. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  285. ;  (only if the high-performance bit is set in driver_function)
  286.  
  287. ;enter with ds:si -> packet, cx = packet length.
  288. ;exit with nc if ok, or else cy if error, dh set to error number.
  289. ;called from telnet layer via software interrupt
  290. ; We just send each byte in turn. No UART interrupts are needed nor wanted.
  291. ; In fact the overdone receiver material omits to note that xmtr interrupts
  292. ; can be lost while processing rcvr ones. Small benefits are no stalled
  293. ; programs, no transmitter buffer, no problems at 19200 b/s. Joe Doupnik
  294. ;
  295. ; Unfortunately the revised code didn't handle hardware handshaking.
  296. ; Added back by Pib, September, 1992.
  297. ;
  298.     assume    ds:nothing, es:nothing
  299.     sti                ; enable interrupts
  300.     cmp    raw_mode,0
  301.     je    not_send_raw
  302. send_raw:
  303.     lodsb
  304.     call    send_char
  305.     loop    send_raw
  306.     clc
  307.     ret
  308. not_send_raw:
  309.   if    ETHERSLIP
  310. ;    
  311. ; Strip off Ethernet header.
  312. ;
  313.     add    si,12
  314.     mov    ax, word ptr ds:[si]
  315.     add    si,2
  316.     sub    cx,14
  317. ;
  318. ; Check packet type.  If an ARP packet then construct an ARP reply
  319. ; packet. Otherwise, process the incoming IP packet.
  320. ;
  321.     cmp    ax,0608h
  322.     jne    noarp
  323.     call    arp_reply
  324.     jmp    send_pkt_end
  325.  
  326. noarp:
  327.   endif
  328. ;
  329. ; Start the SLIP frame.
  330.     mov    al,FR_END        ; Flush out any line garbage
  331.     call    send_char
  332.     jc    send_pkt_end        ; c = failure to send
  333.  
  334.  
  335.   if ETHERAX25
  336.      call    ax25_encap              ; Encapsulate in KISS/AX25
  337.     jc    send_pkt_end
  338.   endif
  339.  
  340. ;
  341. ; Send the data portion of the frame
  342. ;
  343.     call    send_escaped
  344.     jc      send_pkt_end        ; c = failure to send
  345.      mov    al,FR_END        ; terminate it with a FR_END
  346.     call    send_char
  347.     jc    send_pkt_end
  348.     clc
  349. send_pkt_end:
  350.     ret
  351.  
  352.  
  353. ;
  354. ; Send outgoing frame, escaping the SLIP (and KISS) framing characters
  355. ;
  356. send_escaped:
  357.     cmp    cx,0              ; Anything to move?
  358.     je    send_escaped_done     ; Jump if not
  359.  
  360. send_escaped_top:
  361.     lodsb
  362.     cmp    al,FR_ESC          ; escape FR_ESC with FR_ESC and T_FR_ESC
  363.     jne    send_escaped_1
  364.     mov    al,FR_ESC
  365.     call    send_char
  366.     jc    send_escaped_end
  367.     mov    al,T_FR_ESC
  368.     jmp    short send_escaped_2
  369. send_escaped_1:
  370.     cmp    al,FR_END          ; escape FR_END with FR_ESC and T_FR_END
  371.     jne    send_escaped_2
  372.     mov    al,FR_ESC
  373.     call    send_char
  374.     jc    send_escaped_end
  375.     mov    al,T_FR_END
  376. send_escaped_2:
  377.     call    send_char
  378.     jc    send_escaped_end
  379.     loop    send_escaped_top    ; do cx user characters
  380. send_escaped_done:
  381.     clc
  382. send_escaped_end:
  383.     ret
  384.  
  385. ; mod 7/25/89 John Grover
  386. ; redone by Joe Doupnik, Dec 1991
  387. ; CTS check added by Pib, September, 1992.
  388.     assume    ds:nothing, es:nothing
  389. send_char:                ; send the character in al
  390.     push    dx
  391.     push    cx
  392.         push    bx
  393.     xchg    ah,al            ; put data char into ah
  394.     xor    cx,cx            ; 64K retry counter
  395.         mov     bl,hardware_switch      ; Get hardware check (CTS) switch
  396. sendch1:mov    dx,io_addr        ; 03f8h base address
  397.     add    dx,LSR            ; 03fdh get port status
  398.     in    al,dx
  399.     test    al,LSR_THRE        ; Transmitter (THRE) ready?
  400.         jz      sendch4                 ; No -- loop and check again.
  401.         cmp     bl,0                    ; Yes -- check CTS ready if needed.
  402.         jz      sendch2                 ; No check -- send the character.
  403.         mov     dx,io_addr              ; Else get 03f8h base address
  404.         add     dx,MSR                  ; 03fdh get port status
  405.     in    al,dx
  406.         test    al,MSR_CTS              ; Is CTS ready?
  407.         jnz     sendch2                 ; nz = yes
  408. sendch4:jmp     $+2                     ; use time, prevent overdriving UART
  409.     jmp    $+2
  410.     loop    sendch1
  411.     stc                ; carry set for failure
  412.     call    count_out_err
  413.     jmp    short sendch3        ; timeout
  414. sendch2:xchg    al,ah            ; now send it
  415.     mov    dx,io_addr        ; 03f8h, use a little time
  416.     jmp    $+2
  417.     out    dx,al            ; send the byte
  418.     clc                ; status of success
  419. sendch3:pop    bx
  420.     pop    cx
  421.     pop    dx
  422.     ret
  423.  
  424.   if    ETHERSLIP
  425. ;
  426. ; Formulate a dummy ARP reply packet.  ds:si points at the incoming
  427. ; IP packet.
  428. ;
  429.  
  430. arp_reply:
  431.  
  432. ;
  433. ; Save the registers.  Not sure that we need to but it works and I 
  434. ; don't want to change it right now.
  435. ;
  436.     push    ds
  437.     push    es
  438.     push    si
  439.     push    di
  440.     push    cx
  441.  
  442. ;
  443. ; Check to see if the ARP request is to find the hardware address
  444. ; of the local host.  If so, then don't formulate a reply packet.
  445. ;
  446.     mov    cx,4
  447.     mov    ax,si
  448.     mov    di,ax
  449.     mov    ax,ds
  450.     mov    es,ax
  451.     add    di,arp_sprotaddr
  452.     add    si,arp_tprotaddr
  453.     repe    cmpsb            ; Compare source and target
  454.                     ; protocol address
  455.     jnz    arp_reply_2
  456.     pop    cx
  457.     pop    di
  458.     pop    si
  459.     pop    es
  460.     pop    ds
  461.     ret
  462.  
  463. arp_reply_2:
  464. ;
  465. ; Restore registers.
  466. ;
  467.     pop    cx
  468.     pop    di
  469.     pop    si
  470.     push    si
  471.     push    di
  472.     push    cx
  473. ;
  474. ; Restore Ethernet header.
  475. ;
  476.     add    cx,14
  477.     sub    si,14 
  478. ;
  479. ; Ask application layer for a memory buffer in which to store
  480. ; incoming packet.
  481. ;
  482.     push    ds
  483.     push    si            ;save si in case we reject it.
  484.     push    bx
  485.     push    cx
  486.     mov    ax,cs
  487.     mov    es,ax
  488.     mov    ds,ax
  489.     mov    di, offset arp_type
  490.     mov    dl,cs:driver_class
  491.     call    recv_find        ;look up our type.
  492.     pop    cx
  493.     pop    bx
  494.     pop    si
  495.     pop    ds
  496.  
  497.     mov    ax,es            ;is this pointer null?
  498.     or    ax,di
  499.     je    arp_reply_1        ;yes - just free the frame.
  500.  
  501.     push    cx
  502.     push    es
  503.     push    di
  504. ;
  505. ; Save si,di for future use.
  506. ;
  507.     mov    bx,si
  508.     mov    dx,di
  509. ;
  510. ; Set up ARP Reply by first copying the ARP Request packet.
  511. ;
  512.     rep    movsb
  513. ;
  514. ; Skip Ethernet header
  515. ;
  516.     add    bx,14
  517.     add     dx,14
  518. ;
  519. ; Swap target and source protocol addresses from ARP request to ARP 
  520. ; reply packet.
  521. ;
  522.     push    es        ; mods by Joe Doupnik
  523.     mov    si,ds
  524.     mov    es,si
  525.     mov    si,bx        ; incoming packet interior
  526.     sub    si,2+6        ; walk back to originator's Ethernet address
  527.     mov    cx,6        ; six bytes of Ethernet address
  528.     mov    di,dx        ; outgoing packet
  529.     sub    di,2+6+6    ; Ethernet destination address
  530.     rep    movsb        ; copy originator's address as new dest
  531.     pop    es        ;
  532.  
  533.     mov    si,bx
  534.     mov    di,dx    
  535.     mov    cx,4
  536.     add    si,arp_tprotaddr
  537.     add    di,arp_sprotaddr
  538.     rep    movsb
  539.  
  540.     mov    si,bx
  541.     mov    di,dx
  542.     mov    cx,4
  543.     add    si,arp_sprotaddr
  544.     add    di,arp_tprotaddr
  545.     rep    movsb
  546. ;
  547. ; Swap target and source hardware addresses from ARP request to ARP 
  548. ; reply packet.
  549. ;
  550.     mov    si,bx
  551.     mov    di,dx
  552.     mov    cx,6
  553.     add    si,arp_shwaddr
  554.     add    di,arp_thwaddr
  555.     rep    movsb
  556. ;
  557. ; Load source hardware address in ARP reply packet.
  558. ;
  559.     mov    si,bx
  560.     mov    di,dx
  561.     mov    cx,6
  562.     mov    ax,cs
  563.     mov    ds,ax
  564.     mov    si,offset your_addr
  565.     add    di,arp_shwaddr
  566.     rep    movsb
  567. ;
  568. ; Set opcode to REPLY.
  569. ;
  570.     mov    di,dx
  571.     mov    word ptr es:[di].arp_opcode,0200h
  572. ; Give ARP reply packet that has been constructed to the application
  573. ; layer.
  574. ;
  575.     pop    si
  576.     pop    ds
  577.     pop    cx
  578.     assume    ds:nothing
  579.     call    recv_copy
  580.     assume    ds:code
  581.  
  582. arp_reply_1:
  583.  
  584.     pop    cx
  585.     pop    di
  586.     pop    si
  587.     pop    es
  588.     pop    ds
  589.  
  590.     ret
  591.   endif
  592.  
  593.  
  594.     if ETHERAX25
  595. ;
  596. ; Working from the pseudo-Ethernet frame, transmit the KISS and AX.25
  597. ; headers.
  598. ; Leaves si/cx containing the pointer/length of the data portion of the 
  599. ; outgoing frame.
  600.  
  601.   if debug
  602.     public    ax25_encap
  603.   endif
  604. ax25_encap:
  605.  
  606.     push    es            ; Save ES
  607.         mov     ax,ds                   ; Keep caller's DS in ES
  608.     mov    es,ax            ; 
  609.         push    cs                      ; Make DS=CS to access local data
  610.         pop     ds
  611.         assume  ds:code        
  612.     push    bx            ; Save registers which C can trash
  613.     push    dx
  614.         push    cx                      ; Save length of outgoing frame
  615.         push    si                      ; Save pointer to outgoing frame
  616. ;
  617. ; Send the KISS frame type (0 = Data)
  618. ;
  619.         mov     al,0
  620.     call    send_char
  621.     jc    ax25_encap_err        ; c = failure to send
  622. ;
  623. ; Begin the AX.25 layer.
  624. ;   Convert and send destination address from the Ethernet header
  625.     push    es            ; Save register C is allowed to trash
  626.         mov     cx,offset ax25desta     
  627.         push    cx                      ; Near ptr to output buffer
  628.         push    es            ; Far ptr to input buffer (seg)
  629.         push    si                      ; Far ptr to input buffer (offset)
  630.         call    _EtherToAX25
  631.         add     sp,6            ; Discard param                    
  632.     pop    es            ; Restore register
  633.         mov     si,offset ax25desta     ; Point to the AX.25 dest addr
  634.         or      byte ptr [si+ALEN],C or RSRVD
  635.                                         ; UI Frame has the 'C' bit set
  636.         mov     cx,AXALEN               ; Length of an address
  637.     call    send_escaped        ; Send the field
  638.     jc      ax25_encap_err
  639.  
  640. ;
  641. ;   Send our source address, already converted
  642.         mov     si,offset my_ax25    ; Point to AX.25 source addr
  643.     mov     cx,AXALEN               ; Length of an address
  644.     call    send_escaped            ; Send the field
  645.     jc      ax25_encap_err
  646.  
  647. ;   Send the AX.25 control byte
  648.         mov     al,UI                   ; Using UI frames
  649.         call    send_char
  650.         jc      ax25_encap_err
  651. ;
  652. ;   Send the AX.25 PID byte.  The value is determined by the protocol type in
  653. ;   the pseudo-Ethernet frame.
  654.         pop     si                      ; Reload pointer to outgoing frame
  655.         pop     cx                      ; Reload frame length
  656.         add     si,12                   ; Skip to protocol type field
  657.         mov     ax, word ptr es:[si]    ; Get the protocol type
  658.         add     si,2                    ; Skip the protocol type field
  659.         sub     cx,14                   ; Adjust frame length
  660.         
  661.         cmp     ax,ip_type              ; Is it IP?
  662.         jne     ax25_encap_2
  663.         mov     al,PID_IP               ; IP protocol
  664.         call    send_char
  665.         jc      ax25_encap_end         ; Branch if error
  666.         clc                             ; Success
  667.  
  668. ax25_encap_end:
  669.     mov    ax,es            ; Restore caller's DS
  670.     mov    ds,ax
  671.         assume  ds:nothing
  672.     pop    dx            ; Restore registers
  673.     pop    bx
  674.     pop    es            ; Restore saved ES
  675.         ret        
  676.  
  677. ax25_encap_err:                          
  678.         pop     si                      ; Restore saved registers
  679.         pop     cx
  680.         jmp     short ax25_encap_end
  681.  
  682. ax25_encap_2:
  683.         mov     al,PID_ARP              ; ARP Protocol      
  684.         call    send_char
  685.         jc      ax25_encap_end          ; Branch if error
  686.     push    es            ; Save register C can trash
  687.     mov    cx,offset a_arp        ; Near ptr to output buffer
  688.     push    cx
  689.     push    es            ; Far ptr to enet arp packet (seg)
  690.     push    si            ; Far ptr to enet arp packet (offset)
  691.     call    _EArpToAArp        ; Build an AX.25 style ARP frame
  692.     add    sp,6            ; Discard parameters
  693.     pop    es            ; Restore registers
  694.  
  695.     mov    si,offset a_arp        ; Get offset to new ARP packet
  696.     mov    cx,A_ARP_LEN        ; Get packet length
  697.     call    send_escaped        ; Send it
  698.     jc    ax25_encap_end        ; Jump if error
  699.     xor    cx,cx            ; No more original frame to send
  700.     clc        
  701.     jmp    short ax25_encap_end
  702.  
  703.     endif
  704.  
  705.     public    set_address
  706. set_address:
  707. ;set the address of the interface.
  708. ;enter with ds:si -> place to get the address, cx = size of address buffer.
  709. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  710.     assume    ds:nothing
  711.  
  712.   if ETHERAX25
  713. ; We are supplied a pseudo-ethernet address.  Check the length.
  714.     cmp    cx,EADDR_LEN        ; It should be an ethernet address
  715.     je    set_address_1        ; Branch if ok
  716.     mov    dh,BAD_ADDRESS        ; Set return code
  717.     stc
  718.     jmp    short set_address_done
  719.  
  720. set_address_1:
  721. ; Convert the pseudo-ether address back to an AX.25, so we have it for
  722. ; stuffing in packets and comparing to input packets
  723.     push    ds            ; Save DS
  724.     push    bx            ; Save registers C can trash
  725.     push    dx
  726.     mov    ax,cs
  727.     mov    ds,ax            ; Set DS to access local data
  728. ;
  729. ; Convert the receive copy
  730.     mov    ax,offset my_ax25_rx    ; Near ptr to output buffer
  731.     push    ax
  732.     push    ds            ; Far ptr to input buffer (seg)
  733.     push    si            ; Far ptr to input buffer (offset)
  734.     call    _EtherToAX25        ; Convert the address
  735.     add    sp,6
  736. ;
  737. ; Convert the transmit copy
  738.     mov    ax,offset my_ax25    ; Near ptr to output buffer
  739.     push    ax
  740.     push    ds            ; Far ptr to input buffer (seg)
  741.     push    si            ; Far ptr to input buffer (offset)
  742.     call    _EtherToAX25        ; Convert the address
  743.     add    sp,6
  744.  
  745.         mov     si,offset my_ax25    ; Point to converted address
  746.         and     byte ptr [si+ALEN],(not C)
  747.                     ; UI Frame has the 'C' bit clear 
  748.     or      byte ptr [si+ALEN],E or RSRVD
  749.                     ; Source addr has E bit set
  750.  
  751.     pop        dx        ; Restore registers
  752.     pop        bx
  753.     pop        ds        ; Restore DS
  754.   endif    
  755.  
  756.     clc
  757. set_address_done:
  758.     ret
  759.  
  760. ; Actions for switching receive modes
  761. rcv_mode_3:
  762. ;exit raw mode
  763.     mov    raw_mode,0
  764.     ret
  765.  
  766. rcv_mode_6:
  767. ;Enter "promiscuous" mode (for monitoring)
  768. ; Not yet implemented
  769.         ret
  770.  
  771. rcv_mode_7:
  772. ;enter raw mode
  773.     mov    raw_mode,1
  774.     ret
  775.  
  776.  
  777.     public    set_multicast_list
  778. set_multicast_list:
  779. ;enter with ds:si ->list of multicast addresses, ax = number of addresses,
  780. ;  cx = number of bytes.
  781. ;return nc if we set all of them, or cy,dh=error if we didn't.
  782.     mov    dh,NO_MULTICAST
  783.     stc
  784.     ret
  785.  
  786.  
  787.     public    terminate
  788. terminate:
  789.     ret
  790.  
  791.     public    reset_interface
  792. reset_interface:
  793. ;reset the interface.
  794.     assume    ds:code
  795.     ret
  796.  
  797.  
  798. ;called    when we    want to determine what to do with a received packet.
  799. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  800.     extrn    recv_find: near
  801.  
  802. ;called after we have copied the packet into the buffer.
  803. ;enter with ds:si ->the packet, cx = length of the packet.
  804.     extrn    recv_copy: near
  805.  
  806. ;call this routine to schedule a subroutine that gets run after the
  807. ;recv_isr.  This is done by stuffing routine's address in place
  808. ;of the recv_isr iret's address.  This routine should push the flags when it
  809. ;is entered, and should jump to recv_exiting_exit to leave.
  810. ;enter with ax = address of routine to run.
  811.     extrn    schedule_exiting: near
  812.  
  813. ;recv_exiting jumps here to exit, after pushing the flags.
  814.     extrn    recv_exiting_exit: near
  815.  
  816. ;enter with dx = amount of memory desired.
  817. ;exit with nc, dx -> that memory, or cy if there isn't enough memory.
  818.     extrn    malloc: near
  819.  
  820.     extrn    count_in_err: near
  821.     extrn    count_out_err: near
  822.  
  823.     public    recv
  824.  
  825. ;
  826. ; mod 7/25/89 John Grover
  827. ;
  828. ; - added code to check modem status change interrupt. If CTS is
  829. ; - low  turn off transmitter buffer empty interrupt. If CTS is
  830. ; - high turn it on.
  831.  
  832. recv:
  833. ;called from the recv isr.  All registers have been saved, and ds=cs.
  834. ;Upon exit, the interrupt will be acknowledged.
  835.     assume    ds:code
  836.     mov    ax,offset recv_exiting    ;schedule recv_exiting to be called
  837.     call    schedule_exiting    ;  on exit.
  838. recv_2:
  839.     loadport
  840.     setport    IIR
  841.     in    al,dx            ;any interrupts at all?
  842.     test    al,IIR_IP
  843.     jne    recv_1            ;no.
  844.     and    al,IIR_ID
  845.     cmp    al,IIR_RDA        ;Receiver interrupt
  846.     jne    recv_3
  847.     call    asyrxint
  848.     jmp    recv_2
  849. recv_3:
  850. recv_5:
  851. ;process IIR_MSTAT here.
  852. ;  If CTS and packet ready then
  853. ;    enable the    transmit buffer empty interrupt
  854. ;  else
  855. ;    disable the transmit buffer empty interrupt
  856. ;
  857.     cmp    al, IIR_MSTAT
  858.     jne    recv_1
  859. ;    setport    MSR            ; make sure of CTS status
  860. ;    in    al, dx
  861. ;    test    al, MSR_CTS        ; is CTS bit set
  862. ;    jz    recv_5_1        ; no - disable xmit buffer empty int
  863.     jmp    recv_2
  864.  
  865. recv_5_1:
  866.     jmp    recv_2
  867.  
  868. ;process IIR_RLS here
  869. recv_1:
  870.     ret
  871.  
  872.  
  873. ;Process 8250 receiver interrupts
  874. ;
  875. ; mod 7/25/89 John Grover
  876. ; - this branches off when bps < 9600. See asyrxint_a.
  877. ; - Above 9600 bps we go into a loop to process a packet at
  878. ; - a time. If not data ready for a certain amount of time,
  879. ; - the process exits and waits for the next byte. This certain
  880. ; - amount of time to wait depends on the bps and CPU processor speed
  881. ; - and is determined in the initialization of the driver.
  882. ; - Upon receiving the FR_END character for the first frame in the
  883. ; - buffer a semaphore is set which tells recv_frame to run.
  884.  
  885. asyrxint:
  886.  
  887.     movseg    es,ds
  888.     xor    bx, bx
  889.     cmp    baud_rate, 9600         ; below 9600 we're strictly
  890.     jbe    asyrxint_a              ; interrupt driven
  891.     mov    bx, xmit_time
  892. asyrxint_a:
  893.     mov    di,recv_buf_tail
  894.     xor    bp, bp            ; set flag to indicate 1st char
  895.                     ; processed
  896.     mov    si, packet_sem          ; optimization
  897.     loadport
  898.     mov    ah, LSR_DR
  899.  
  900. asyrxint_again:
  901.     xor    cx, cx            ; initialize counter
  902.     setport    LSR
  903. asyrxint_in:
  904.     in    al,dx            ; check for data ready
  905.     test    al,LSR_DR
  906.     jnz    asyrxint_gotit        ; yes - break out of loop
  907.     inc    cx            ; no - increase loop counter
  908.     cmp    cx, bx            ; timeout?
  909.     jae    asyrxint_exit        ; yes - leave
  910.     jmp    asyrxint_in        ; no - keep looping
  911.  
  912. asyrxint_gotit:
  913.     setport    RBR
  914.     in    al,dx
  915.  
  916. ;Process incoming data;
  917. ; If buffer is full, we have no choice but
  918. ; to drop the character
  919.     cmp    di,recv_buf_head    ; check for buffer collision
  920.     jne    asyrxint_ok        ; none - continue
  921.     or    si, si                  ; maybe - if there are packets
  922.     jnz    asyrxint_exit        ; yes exit
  923.  
  924. asyrxint_ok:
  925.     stosb
  926.  
  927.     cmp    di,recv_buf_end        ; did we hit the end of the buffer?
  928.     jne    asyrxint_3        ; no.
  929.     mov    di,recv_buf        ; yes - wrap around.
  930.  
  931. asyrxint_3:
  932.     cmp    raw_mode,0        ;raw mode?
  933.     jne    asyrxint_raw
  934.     cmp    al,FR_END        ; might    this be    the end of a frame?
  935.     jne    asyrxint_reset        ; no - reset flag and loop
  936. asyrxint_raw:
  937.     inc    si                      ; yes - indicate packet ready
  938.     cmp    si, 1                   ; determine if semaphore is <> 1
  939.     jne    asyrxint_chk_flg        ; yes - recv_frame must be active
  940.     inc    recv_pkt_ready          ; no - set flag to start recv_frame
  941.  
  942. asyrxint_chk_flg:
  943.     cmp    bp, 0                   ; was this the first char?
  944.     jne    asyrxint_1              ; no - exit handler
  945. asyrxint_reset:
  946.     inc    bp            ; set 1st character flag
  947.     jmp    asyrxint_again        ; get another character
  948.  
  949. asyrxint_exit:
  950. asyrxint_1:
  951.     mov    recv_buf_tail,di
  952.     mov    packet_sem, si
  953.  
  954.     ret
  955.  
  956.  
  957. ; --------------------------------------------------------------
  958. ;
  959. ;  recv_exiting
  960. ;
  961. recv_exiting:
  962.     assume    ds:nothing
  963.     pushf
  964.     cmp    recv_pkt_ready, 1       ; is a packet ready?
  965.     jne    recv_isr_exit           ; no - skip to end
  966.     push    ax
  967.     push    bx
  968.     push    cx
  969.     push    dx
  970.     push    ds
  971.     push    es
  972.     push    bp
  973.     push    di
  974.     push    si
  975.     movseg    ds,cs
  976.     assume    ds:code
  977.     mov    recv_pkt_ready,    0    ; reset flag
  978.     sti                ; enable interrupts
  979.  
  980.     call    recv_frame
  981.  
  982.     pop    si
  983.     pop    di
  984.     pop    bp
  985.     pop    es
  986.     pop    ds
  987.     pop    dx
  988.     pop    cx
  989.     pop    bx
  990.     pop    ax
  991. recv_isr_exit:
  992.     jmp    recv_exiting_exit
  993.  
  994.  
  995. ; --------------------------------------------------------------
  996. ;
  997. ;  recv_frame
  998. ;
  999. ; mod 7/25/89 John Grover
  1000. ;
  1001. ; - recv_frame now operates with interrupts on. It is triggered
  1002. ; - by the recv_pkt_ready flag and continues until all bytes
  1003. ; - in all packets in the buffer have been transmitted to the upper
  1004. ; - layer.
  1005. ;
  1006. recv_frame_end:
  1007.     dec    packet_sem
  1008.     cmp    packet_sem, 0        ; are there more packets ready?
  1009.     jnz    recv_frame                 ; yes - execute again
  1010.     ret
  1011.  
  1012.   ifdef debug
  1013.     public    recv_frame
  1014.   endif
  1015. recv_frame:
  1016.     cmp    packet_sem, 0        ; should we do this?
  1017.     jz    recv_frame_end        ; no - exit
  1018.     mov    si,recv_buf_head    ;process characters.
  1019.     xor    cx,cx            ;count up the size here.
  1020.     cmp    raw_mode,0        ;raw mode?
  1021.     je    recv_frame_1        ;no, interpret escapes, etc.
  1022.     cmp    si,recv_buf_tail    ;any more characters?
  1023.     je    recv_frame_end
  1024. recv_frame_raw_1:
  1025.     inc    cx            ;count a character.
  1026.     call    recv_char
  1027.     cmp    si,recv_buf_tail
  1028.     jne    recv_frame_raw_1
  1029.     jmp    short recv_frame_2    ;we have the count here.
  1030.  
  1031. recv_frame_1:
  1032.     call    recv_char        ;get a char.
  1033.     je    recv_frame_2        ;go if no more chars.
  1034.     cmp    al,FR_ESC        ;an escape?
  1035.     je    recv_frame_1        ;yes - don't count this char.
  1036.     inc    cx            ;no - count this one.
  1037.     jmp    recv_frame_1
  1038. recv_frame_2:
  1039.  
  1040.     jcxz    recv_frame_3        ;count zero? yes - free the frame
  1041.     jmp    recv_frame_4
  1042.  
  1043. ; Discard the current frame.
  1044. recv_frame_3:
  1045.     mov    recv_buf_head,si    ;remember the new starting point.
  1046.     jmp    recv_frame_end
  1047.  
  1048. recv_frame_4:
  1049.  
  1050.   if    ETHERSLIP
  1051. ;
  1052. ; Add Ethernet header.  As well, ensure that minimum packet size is 60
  1053. ; bytes; some application packages actually check for minimum packet size.
  1054. ;
  1055.     cmp    raw_mode,0        ;in raw mode, we don't fake Ethernet.
  1056.     jne    recv_next
  1057.     add    cx,14 
  1058.     cmp    cx, 60
  1059.     jge     recv_next
  1060.     mov    cx, 60    
  1061. recv_next:
  1062.  
  1063.   else
  1064.     if ETHERAX25
  1065. ;
  1066. ; Adjust for the Ethernet header (which we add) minus the AX.25 header
  1067. ; which will be stripped off. Also, ensure minimum packet size as above.
  1068.     cmp    raw_mode,0        ;in raw mode, we don't fake Ethernet.
  1069.     jne    recv_next
  1070.     sub    cx,AX25_HDR_LEN - 14    ;Adjust for headers
  1071.     cmp    cx, 60
  1072.     jge     recv_next
  1073.     mov    cx, 60    
  1074. recv_next:
  1075. ;
  1076. ; Un-slip the AX.25 packet header. If cy set, packet was not one we
  1077. ; needed to handle.
  1078.     push    si            ; Save previous posn at end of frame
  1079.     mov    si,recv_buf_head    ; Start again at the beginning
  1080.     call    ax25_decap
  1081.     jnc    recv_next_1        ; Branch if we're keeping the frame 
  1082.      pop    si            ; Put back previous position
  1083.     jmp    recv_frame_3        ; Go discard the frame
  1084.  
  1085. recv_next_1:
  1086.     mov    recv_buf_head,si    ; Discard the KISS/AX25 part of frame
  1087.     pop    si            ; Put back previous position
  1088.     endif
  1089.  
  1090. ; No header adjustments needed for regular SLIP
  1091.   endif
  1092.  
  1093.     push    cx            ;save the count.
  1094.     push    si            ;save si in case we reject it.
  1095.     push    bx
  1096.   if    ETHERSLIP
  1097.     movseg    es,cs
  1098.     mov    di,offset ip_type
  1099.   else
  1100.     if ETHERAX25
  1101. ; Registers already set up by ax25_decap
  1102.     else
  1103.     MOV    DI,CS
  1104.     MOV    ES,DI
  1105.     mov    di,0
  1106.     endif
  1107.   endif
  1108.     mov    dl,cs:driver_class
  1109.     call    recv_find        ;look up our type.
  1110.     pop    bx
  1111.     pop    si
  1112.     pop    cx
  1113.  
  1114.     mov    ax,es            ;is this pointer null?
  1115.     or    ax,di
  1116.     je    recv_frame_3        ;yes - just free the frame.
  1117.  
  1118.     push    cx
  1119.     push    es            ;remember where the buffer pointer is
  1120.     push    di
  1121.  
  1122.   if    ETHERSLIP or ETHERAX25
  1123. ;
  1124. ; Add pseudo-Ethernet header to the start of the frame.
  1125.     call    fix_header
  1126.   endif
  1127.  
  1128.     mov    si,recv_buf_head    ;process characters from start of frame
  1129.     cmp    raw_mode,0        ;raw mode?
  1130.     je    recv_frame_5        ;no, interpret characters.
  1131. recv_frame_raw_2:
  1132.     call    recv_char        ;get a character.
  1133.     stosb                ;store it.
  1134.     loop    recv_frame_raw_2    ;get another.
  1135.     jmp    short recv_frame_6    ;all done.
  1136.  
  1137. recv_frame_5:
  1138.     call    recv_escaped        ; Unslip the remainder of the frame
  1139.  
  1140. recv_frame_6:
  1141.     mov    recv_buf_head,si    ;we're skipped to the end.
  1142.  
  1143.   if ETHERAX25
  1144. ; If this was an ARP frame, then we need to translate it to Ethernet format.
  1145. ; Translation happens in-place in the destination buffer.
  1146.     cmp    ax25_pid,PID_ARP    ; Is this ARP?
  1147.     jne    recv_frame_7        ; Branch if not
  1148.     pop    di            ; Refresh ptr/size of frame
  1149.     pop    ax            
  1150.     pop    cx
  1151.     sub    cx,(2*(AXALEN-6))    ; Frame will shrink 
  1152.     push    cx            ; Save ptr/size again
  1153.     push    ax
  1154.     push    di
  1155.     push    es            ; Save registers C can trash
  1156.     add    di,14            ; Bump ptr past the Ethernet header
  1157.     push    es            ; Far ptr to the translated pkt (seg)
  1158.     push    di            ; Far ptr to the translated pkt 
  1159.     push    es            ; Far ptr to the untranslated pkt (seg)
  1160.     push    di            ; Far ptr to the untranslated pkt 
  1161.     call    _AArpToEArp        ; Translate the ARP frame
  1162.     add    sp,8        
  1163.     pop    es            ; Restore register
  1164.   endif
  1165. recv_frame_7:
  1166.     pop    si            ;now give the frame to the client.
  1167.     pop    ds
  1168.     pop    cx
  1169.     assume    ds:nothing
  1170.     call    recv_copy
  1171.     movseg    ds,cs
  1172.     assume    ds:code
  1173.     jmp    recv_frame_end
  1174.  
  1175.  
  1176. ; --------------------------------------------------------------
  1177. ;
  1178. ;  recv_char
  1179. ;
  1180. ; mod 7/25/89 John Grover
  1181. ; - Now    uses buffer pointers to determine if there are
  1182. ; - characters left.
  1183. ;
  1184.  
  1185. recv_char:
  1186. ;enter with si -> receive buffer, bx = receive count.  Wrap around if needed.
  1187. ;return with nz, al = next char.  Return zr if there are no more chars in
  1188. ;  this frame.
  1189. ;
  1190.     lodsb
  1191.     cmp    si,recv_buf_end
  1192.     jb    recv_char_1
  1193.     mov    si,recv_buf
  1194. recv_char_1:
  1195.     cmp    si, recv_buf_tail
  1196.     je    recv_char_2
  1197.     cmp    al,FR_END
  1198. recv_char_2:
  1199.     ret
  1200.  
  1201. ;
  1202. ; Move cx bytes (or whatever remains) of a frame from the recv_buf 
  1203. ; into a destination buffer, handling the SLIP escape characters.
  1204. ;     ds:si - data in the recv buffer
  1205. ;    es:di - destination buffer
  1206. ;    cx - count of bytes to receive
  1207. recv_escaped:
  1208.     cmp    cx,0            ; Anything to move?
  1209.     je    recv_escaped_end    ; Branch if not
  1210.  
  1211. recv_escaped_1:
  1212.     call    recv_char
  1213.     je    recv_escaped_end    ;Nothing left - we're all done.
  1214.     cmp    al,FR_ESC        ;an escape?
  1215.     jne    recv_escaped_2        ;no - just store it.
  1216.  
  1217.     call    recv_char        ;get the next character.
  1218.     je    recv_escaped_end    ;Nothing left
  1219.     cmp    al,T_FR_ESC
  1220.     mov    al,FR_ESC        ;assume T_FR_ESC
  1221.     je    recv_escaped_2        ;yup, that's it    - store FR_ESC
  1222.     mov    al,FR_END        ;nope, store FR_END
  1223. recv_escaped_2:
  1224.     stosb                ;store the byte.
  1225.     loop    recv_escaped_1
  1226.  
  1227. recv_escaped_end:
  1228.     ret
  1229.  
  1230.   if    ETHERSLIP
  1231. ;
  1232. ; Set destination and source addressess and packet type in an
  1233. ; Ethernet header.
  1234. ;
  1235. fix_header:
  1236. ;
  1237. ; Set destination address.
  1238.     mov    ax,0000h
  1239.     stosw
  1240.     mov    ax,0c3c4h
  1241.     stosw
  1242.     mov    ax,0c2cch
  1243.     stosw
  1244. ;
  1245. ; Set source address.
  1246.     mov    ax,0201h
  1247.     stosw
  1248.     mov    ax,0403h
  1249.     stosw
  1250.     mov    ax,0605h
  1251.     stosw
  1252. ;
  1253. ; Set packet type to IP.
  1254.     mov    ax, 0008h
  1255.     stosw    
  1256.     ret
  1257.   endif
  1258.  
  1259.   if ETHERAX25
  1260. ;
  1261. ; Set the destination address, source address, and protocol type in 
  1262. ; a pseudo-Ethernet packet header.
  1263. ; Inputs:
  1264. ;    es:di - pointer to the destination buffer
  1265. ;    ds:ax25header - the addresses and protocol in AX.25 form
  1266.  if debug
  1267.     public    fix_header
  1268.  endif
  1269.  
  1270. fix_header:
  1271.     push    cx            ; Save registers C can trash
  1272.     push    es
  1273.     push    es            ; Far ptr to output buffer (seg)
  1274.     push    di            ; Far ptr to output buffer (ofs)
  1275.     push    ds            ; Far ptr to input buffer (seg)
  1276.     mov    ax,offset ax25_dst    ; Far ptr to input buffer (ofs)
  1277.     push    ax
  1278.     call    _AX25ToEther        ; Convert frame destination addr
  1279.     add    sp,8
  1280.     pop    es            ; Get back output buffer segment
  1281.     push    es            ; Save registers C can trash
  1282.     add    di,6            ; Advance to frame source addr field
  1283.     push    es            ; Far ptr to output buffer (seg)
  1284.     push    di            ; Far ptr to output buffer (ofs)
  1285.     push    ds            ; Far ptr to input buffer (seg)
  1286.     mov    ax,offset ax25_src    ; Far ptr to input buffer (ofs
  1287.     push    ax
  1288.      call    _AX25ToEther        ; Convert frame source addr
  1289.     add    sp,8
  1290.     pop    es            ; Restore registers
  1291.     pop    cx
  1292.     add    di,6            ; Advance to protocol type field
  1293.     mov    ax,ip_type        ; Assume this is an IP packet
  1294.     cmp    ax25_pid,PID_IP        ; Is it?
  1295.     je    fix_header_1        ; Branch if we guessed right
  1296.     mov    ax,arp_type        ; Must be ARP packet
  1297. fix_header_1:
  1298.     stosw                ; Store the protocol type
  1299.     ret
  1300.  
  1301. ;
  1302. ; Remove the KISS and AX.25 encapsulation from a frame in the recv buffer,
  1303. ; leaving the AX.25 header in the buffer at ax25header.  Determine if the
  1304. ; frame is one we can handle and return the appropriate status.
  1305. ; Inputs:
  1306. ;    ds:si - the frame to be decoded
  1307. ; Outputs:
  1308. ;    decoded AX.25 header in axheader
  1309. ;    si - updated past the KISS and AX.25 layers        
  1310. ;    di - pointer to the Ethernet protocol type for this frame
  1311. ;    es - = cs
  1312. ;    cy clear if success, cy set if frame should be discarded.
  1313. ; Modifies:
  1314. ;    di, es, ax
  1315.  
  1316. ax25_decap:
  1317.     push    cx            ; Save register
  1318.     add2    ax25_stat_in,1        ; Count the frame
  1319.      mov    cx,AX25_HDR_LEN        ; Number of bytes to unpack
  1320.     movseg    es,cs            ; Point to the result buffer
  1321.     mov    di,offset ax25header
  1322.     call    recv_escaped        ; Copy/unescape the data
  1323.  
  1324.     cmp    ax25_kiss,0        ; Is it KISS type: data?
  1325.     jne    ax25_decap_bad        ; Branch if not - bad packet
  1326.     
  1327.     test    ax25_src+ALEN,E        ; Is addr extension bit set?
  1328.     je    ax25_decap_unsup    ; If not, this isn't a simple address
  1329.  
  1330.     and    ax25_src+ALEN,SSID    ; Clear the non-SSID bits
  1331.     and    ax25_dst+ALEN,SSID    ; in both addresses
  1332.  
  1333.     push    si            ; Save remainder of frame
  1334.     mov    si,offset my_ax25_rx    ; Offset to our address
  1335.     mov    di,offset ax25_dst    ; Offset to AX.25 destination addr
  1336.     mov    cx,AXALEN        ; Length of addresses
  1337.     repe     cmpsb            ; Compare addresses
  1338.     pop    si
  1339.     je    ax25_decap_1        ; Branch if a match
  1340.     stc                ; Drop the frame
  1341.     jmp    short ax25_decap_end
  1342.  
  1343. ax25_decap_1:
  1344.     add2    ax25_stat_ours,1    ; Count the packet
  1345.     cmp    ax25_control,UI        ; Is this a plain UI frame?
  1346.     je    ax25_decap_2        ; Branch if ok
  1347.     jmp    short ax25_decap_unsup    ; 
  1348.  
  1349. ax25_decap_2:
  1350.     cmp    ax25_pid,PID_IP        ; Is it an IP frame?
  1351.     jne    ax25_decap_3        ; Branch if not
  1352.     mov    di,offset ip_type    ; Set ptr to the protocol type
  1353.     clc                ; Success
  1354.     jmp    short ax25_decap_end
  1355. ax25_decap_3:
  1356.     cmp    ax25_pid,PID_ARP    ; How about an ARP frame?
  1357.     jne    ax25_decap_unsup    ; Nope - something we don't handle
  1358.     mov    di,offset arp_type    ; Set ptr to the protocol type
  1359.     clc                ; Success
  1360.  
  1361. ax25_decap_end:
  1362.     pop    cx            ; Restore register
  1363.     ret
  1364.  
  1365. ax25_decap_bad:
  1366.     add2    ax25_stat_bad,1        ; Count the bad packet
  1367.     call    count_in_err    
  1368.     stc                
  1369.     jmp    short ax25_decap_end
  1370.  
  1371. ax25_decap_unsup:
  1372.     add2    ax25_stat_unsup,1    ; Count unsupported packet
  1373.     call    count_in_err
  1374.     stc
  1375.     jmp    short ax25_decap_end
  1376.  
  1377.   endif
  1378.  
  1379. ;Set bit(s) in I/O port
  1380. setbit:
  1381. ;enter with dx = port, ah = bit to set.
  1382.     in    al,dx
  1383.     or    al,ah
  1384.     out    dx,al
  1385.     ret
  1386.  
  1387.  
  1388. ;Clear bit(s) in I/O port
  1389. clrbit:
  1390. ;enter with dx = port, ah = bit to set.
  1391.     in    al,dx
  1392.     not    al            ;perform an and-not using DeMorgan's.
  1393.     or    al,ah
  1394.     not    al
  1395.     out    dx,al
  1396.     ret
  1397.  
  1398.  
  1399.     public    timer_isr
  1400. timer_isr:
  1401. ;if the first instruction is an iret, then the timer is not hooked
  1402.     iret
  1403.  
  1404. ;any code after this will not be kept after initialization. Buffers
  1405. ;used by the program, if any, are allocated from the memory between
  1406. ;end_resident and end_free_mem.
  1407.     public end_resident,end_free_mem
  1408. end_resident    label    byte
  1409.     db    3000 dup(?)
  1410. end_free_mem    label    byte
  1411.  
  1412.     public    usage_msg
  1413.   if    ETHERSLIP
  1414. usage_msg    db    "usage: ETHERSLIP [options] <packet_int_no> [-h] [hardware_irq]",CR,LF
  1415.         db    "   [io_addr] [baud_rate]",CR,LF
  1416.         db    "   [send_buf_size] [recv_buf_size]",CR,LF
  1417.         db    "   -h enables hardware handshaking",CR,LF,'$'
  1418.  
  1419.     public    copyright_msg
  1420. copyright_msg    db    "Packet driver for ETHERSLIP, version ",'0'+(majver / 10),'0'+(majver mod 10),"."
  1421.         db    '0'+version,CR,LF
  1422.         db    "Portions Copyright 1988 Phil Karn",CR,LF,'$'
  1423.         db    "Portions Copyright 1991 Michael Martineau",CR,LF
  1424.         db    " 5 Nov 1991",cr,lf,'$'
  1425.   else
  1426.     if ETHERAX25
  1427. usage_msg    db    "usage: ETHRAX25 [options] <packet_int_no> [-h] [hardware_irq]",CR,LF
  1428.         db    "   [io_addr] [baud_rate]",CR,LF
  1429.         db    "   [send_buf_size] [recv_buf_size]",CR,LF
  1430.         db    "   -h enables hardware handshaking",CR,LF,'$'
  1431.  
  1432.     public    copyright_msg
  1433. copyright_msg    db    "Packet driver for Ethernet to AX.25, version ",'0'+(majver / 10),'0'+(majver mod 10),"."
  1434.         db    '0'+version,CR,LF
  1435.         db    "ETHRAX25 revision ",axversion,CR,LF
  1436.         db    "Portions Copyright 1988 Phil Karn",CR,LF,'$'
  1437.         db    "Portions Copyright 1991 Michael Martineau",CR,LF
  1438.         db    " 5 Nov 1991",cr,lf,'$'
  1439.     else
  1440. usage_msg    db    "usage: SLIP8250 [options] <packet_int_no> "
  1441.         db    "[-h] [driver_class] [hardware_irq]",CR,LF
  1442.         db    "   [io_addr] [baud_rate]",CR,LF
  1443.         db    "   [recv_buf_size]",CR,LF
  1444.         db    "   -h enables hardware handshaking",CR,LF
  1445.         db    "   The driver_class should be SLIP, KISS, AX.25,"
  1446.         db    " or a number.",CR,LF,'$'
  1447.  
  1448.     public    copyright_msg
  1449. copyright_msg    db    "Packet driver for SLIP8250, version "
  1450.         db    '0'+(majver / 10),'0'+(majver mod 10),".",'0'+version,CR,LF
  1451.         db    "Portions Copyright 1988 Phil Karn",CR,LF
  1452.         db    "Portions Copyright 1991 Joe Doupnik",CR,LF
  1453.                 db      "Hardware flow-control mods by Philip R. Burns",CR,LF
  1454.         db    "Portions Copyright 1992 Crynwr Software",CR,LF,'$'
  1455.     endif
  1456.   endif
  1457.  
  1458. approximate_msg    db    "Warning: This baud rate can only be approximated"
  1459.         db    "using the 8250",CR,LF
  1460.         db    "because it is not an even divisor of 115200"
  1461.         db    CR,LF,'$'
  1462.  
  1463. is_16550_msg    db      "16550 Uart detected, FIFO will be used",CR,LF,'$'
  1464.  
  1465. no_memory_msg    db    "Unable to allocate enough memory, look at end_resident in SLIP8250.ASM",CR,LF,'$'
  1466.  
  1467. class_name_ptr    dw    ?
  1468. class_name    db    "Interface class ",'$'
  1469.   if ETHERSLIP OR ETHERAX25
  1470.   else
  1471. kiss_name    db    "KISS",CR,LF,'$'
  1472. ax25_name    db    "AX.25",CR,LF,'$'
  1473. slip_name    db    "SLIP",CR,LF,'$'
  1474.   endif
  1475. int_no_name    db    "Interrupt number ",'$'
  1476. io_addr_name    db    "I/O port ",'$'
  1477. baud_rate_name    db    "Baud rate ",'$'
  1478. recv_buf_name    db    "Receive buffer size ",'$'
  1479. unusual_com1    db    "That's unusual!  Com1 (0x3f8) usually uses IRQ 4!"
  1480.         db    CR,LF,'$'
  1481. unusual_com2    db    "That's unusual!  Com2 (0x2f8) usually uses IRQ 3!"
  1482.         db    CR,LF,'$'
  1483.  
  1484.     extrn    set_recv_isr: near
  1485.     extrn    maskint: near
  1486.  
  1487. ;enter with si -> argument string, di -> word to store.
  1488. ;if there is no number, don't change the number.
  1489.     extrn    get_number: near
  1490.  
  1491. ;enter with dx -> name of word, di -> dword to print.
  1492.     extrn    print_number: near
  1493.  
  1494. ;enter with si -> argument string.
  1495. ;skip spaces and tabs.  Exit with si -> first non-blank char.
  1496.     extrn    skip_blanks: near
  1497.  
  1498.  
  1499. ;-> the assigned Ethernet address of the card.
  1500.     extrn    rom_address: byte
  1501.  
  1502.     public    parse_args
  1503. parse_args:
  1504. ;exit with nc if all went well, cy otherwise.
  1505.     call    skip_blanks
  1506.     cmp    al,'-'            ;did they specify a switch?
  1507.     jne    not_switch
  1508.     cmp    byte ptr [si+1],'h'    ;did they specify '-h'?
  1509.     je    got_hardware_switch
  1510.     stc                ;no, must be an error.
  1511.     ret
  1512. got_hardware_switch:
  1513.     mov    hardware_switch,1
  1514.     add    si,2            ;skip past the switch's characters.
  1515.     jmp    parse_args        ;go parse more arguments.
  1516. not_switch:
  1517.   if ETHERSLIP OR ETHERAX25
  1518.   else
  1519.     or    al,20h            ; to lower case (assuming letter)
  1520.     cmp    al,'k'
  1521.     jne    parse_args_2
  1522.     mov    driver_class,10        ;KISS, from packet spec
  1523.     mov    dx,offset kiss_name
  1524.     jmp    short parse_args_1
  1525. parse_args_2:
  1526.     cmp    al,'s'
  1527.     jne    parse_args_3
  1528.     mov    driver_class,6        ;SLIP, from packet spec
  1529.     mov    dx,offset slip_name
  1530.     jmp    short parse_args_1
  1531. parse_args_3:
  1532.     cmp    al,'a'
  1533.     jne    parse_args_4
  1534.     mov    driver_class,9        ;AX.25, from packet spec.
  1535.     mov    dx,offset ax25_name
  1536.     jmp    short parse_args_1
  1537. parse_args_4:
  1538.     mov    di,offset driver_class
  1539.     mov    bx,offset class_name
  1540.     call    get_number
  1541.     mov    class_name_ptr,0
  1542.     jmp    short parse_args_6
  1543. parse_args_1:
  1544.     mov    class_name_ptr,dx
  1545. parse_args_5:
  1546.     mov    al,[si]            ;skip to the next blank or CR.
  1547.     cmp    al,' '
  1548.     je    parse_args_6
  1549.     cmp    al,CR
  1550.     je    parse_args_6
  1551.     inc    si            ;skip the character.
  1552.     jmp    parse_args_5
  1553. parse_args_6:
  1554.   endif
  1555.     mov    di,offset int_no
  1556.     call    get_number
  1557.     mov    di,offset io_addr
  1558.     call    get_number
  1559.     mov    di,offset baud_rate
  1560.     call    get_number
  1561.     mov    di,offset recv_buf_size
  1562.     call    get_number
  1563.     clc
  1564.     ret
  1565.  
  1566.  
  1567. ; --------------------------------------------------------------
  1568. ;
  1569. ;  etopen
  1570. ;
  1571. ; mod 7/25/89 John Grover
  1572. ; - Contains a loop to determine a pseudo timeout for asyrxint.
  1573. ; - The value is determined by transmitting characters in a
  1574. ; - loop whose clock cycles are nearly the same as the "sister"
  1575. ; - loop in asyrxint. The per character, maximum time used
  1576. ; - basis which is then multiplied by a factor to achieve a timeout
  1577. ; - value for the particular bps and CPU speed of the host.
  1578.  
  1579.     public    etopen
  1580. etopen:
  1581.     mov    al,int_no
  1582.     call    maskint            ;disable these interrupts.
  1583.  
  1584.   if ETHERSLIP
  1585. ;
  1586. ; Pseudo-Ethernet address to return when get_address() is called.
  1587. ;
  1588.     mov    word ptr rom_address[0],2*256+0    ;locally assigned
  1589.     mov    word ptr rom_address[2],0*256+12h
  1590.     mov    word ptr rom_address[4],34h*256+56h
  1591.   endif
  1592.  
  1593.   if ETHERAX25
  1594. ;
  1595. ; Pseudo-Ethernet address to return when get_address() is called: "NOCALL"
  1596.     mov    word ptr rom_address[0],84h*256+0
  1597.     mov    word ptr rom_address[2],3eh*256+02h
  1598.     mov    word ptr rom_address[4],00h*256+17h
  1599.   endif
  1600.  
  1601. ;
  1602. ; mod  3/16/90  Denis DeLaRoca
  1603. ; - determine if 16550 uart is present
  1604. ; - if so initialize fifo buffering
  1605. ;
  1606.     loadport
  1607.     setport    FCR
  1608.     mov    al,FIFO_ENABLE
  1609.     out    dx,al                   ;outportb(base+FCR,(char) FIFO_ENABLE)
  1610.     setport    IIR
  1611.     in    al,dx                   ;inportb(base+IIR)
  1612.     and    al,IIR_FIFO_ENABLED     ;     & IIR_FIFO_ENABLED
  1613.     cmp    al,IIR_FIFO_ENABLED    ;both bits must be on   NEW, 11/20/90
  1614.     jnz    not_16550               ;nope, we don't have 16550 chip
  1615.     mov    is_16550,1              ;yes, note fact
  1616.     mov    al,FIFO_SETUP           ;and setup FIFO
  1617.     setport    FCR
  1618.     out    dx,al                   ;outportb(base+FCR,(char) FIFO_SETUP)
  1619.  
  1620.     mov    dx,offset is_16550_msg
  1621.     mov    ah,9
  1622.     int    21h            ;let user know about 16550
  1623.  
  1624. not_16550:
  1625.     loadport            ;Purge the receive data buffer
  1626.     setport    RBR
  1627.     in    al,dx
  1628.  
  1629.     ;Set line control register: 8 bits, no parity
  1630.     mov    al,LCR_8BITS
  1631.     setport    LCR
  1632.     out    dx,al
  1633.  
  1634.     ;Turn on receive interrupt enable in 8250, leave transmit
  1635.     ; and modem status interrupts turned off for now
  1636.     mov    al,IER_DAV
  1637.     setport    IER
  1638.     out    dx,al
  1639.  
  1640.     ;Set modem control register: assert DTR, RTS, turn on 8250
  1641.     ; master interrupt enable (connected to OUT2)
  1642.  
  1643.     mov    al,MCR_DTR or MCR_RTS or MCR_OUT2
  1644.     setport    MCR
  1645.     out    dx,al
  1646.  
  1647. ;compute the divisor given the baud rate.
  1648.     mov    dx,baudclk+2
  1649.     mov    ax,baudclk
  1650.     mov    bx,0
  1651. asy_speed_1:
  1652.     inc    bx
  1653.     sub    ax,baud_rate
  1654.     sbb    dx,baud_rate+2
  1655.     jnc    asy_speed_1
  1656.     dec    bx
  1657.     add    ax,baud_rate
  1658.     adc    dx,baud_rate+2
  1659.     or    ax,dx
  1660.     je    asy_speed_2
  1661.  
  1662.     mov    dx,offset approximate_msg
  1663.     mov    ah,9
  1664.     int    21h
  1665.  
  1666. asy_speed_2:
  1667.  
  1668.     loadport            ;Purge the receive data buffer
  1669.     setport    RBR
  1670.     in    al,dx
  1671.  
  1672.     mov    ah,LCR_DLAB        ;Turn on divisor latch access bit
  1673.     setport    LCR
  1674.     call    setbit
  1675.  
  1676.     mov    al,bl            ;Load the two bytes of the divisor.
  1677.     setport    DLL
  1678.     out    dx,al
  1679.     mov    al,bh
  1680.     setport    DLM
  1681.     out    dx,al
  1682.  
  1683.     mov    ah,LCR_DLAB        ;Turn off divisor latch access bit
  1684.     setport    LCR
  1685.     call    clrbit
  1686.  
  1687. ;set up the various pointers.
  1688.  
  1689.     mov    dx,recv_buf_size
  1690.     call    malloc
  1691.     jnc    have_memory
  1692.     mov    dx,offset no_memory_msg
  1693.     stc
  1694.     ret
  1695. have_memory:
  1696.     mov    recv_buf,dx
  1697.     mov    recv_buf_head,dx
  1698.     mov    recv_buf_tail,dx
  1699.     add    dx,recv_buf_size
  1700.     mov    recv_buf_end,dx
  1701.  
  1702.     ; the following code attempts to determine a pseudo timeout
  1703.     ; value    to use in the loop that waits for an incoming character
  1704.     ; in asyrxint. The value returned in xmit_time is the number of
  1705.     ; loops processed between characters - therefore the loop used below
  1706.     ; is and should    remain similar to the loop used in asyrxint.
  1707.  
  1708.     xor    ax, ax            ; we'll send a 0
  1709.     mov    ah, LSR_THRE
  1710.     mov    cx, 10h            ; take the highest of 16 runs
  1711.     xor    si, si            ; will hold highest value
  1712.  
  1713. xmit_time_start:
  1714.  
  1715.     xor    di, di            ; initialize counter
  1716.     loadport
  1717.     setport    THR            ; xmit a character
  1718.     out    dx, al
  1719.     setport    LSR               ; set up    to check for an empty buffer
  1720.  
  1721.     ; next is the loop actually being timed
  1722.  
  1723. xmit_time_top:
  1724.     in    al, dx
  1725.     test    al, ah
  1726.     jnz    xmit_time_done
  1727.     inc    di
  1728.     cmp    cx, cx            ; these next few instructions do nothing
  1729.     jmp    xmit_time_1        ;  except maintain similarity with the
  1730.                     ;  "sister" loop in asyrxint
  1731. xmit_time_1:
  1732.     jmp    xmit_time_top
  1733.  
  1734. xmit_time_done:                ; end of timed loop
  1735.  
  1736.  
  1737.  
  1738.     cmp    si, di            ; compare highest value with new value
  1739.     ja    xmit_time_end        ; no bigger - just loop
  1740.     mov    si, di            ; bigger - save it
  1741.  
  1742. xmit_time_end:
  1743.     loop    xmit_time_start        ; bottom of outer loop
  1744.  
  1745.     shl    si, 1            ; we'll wait 8 characters worth
  1746.     shl    si, 1
  1747.     shl    si, 1
  1748.     mov    xmit_time, si        ; retain largest value
  1749.  
  1750.     ; end of pseudo timer determination
  1751.  
  1752.     call    set_recv_isr        ;Set interrupt vector to SIO handler
  1753.  
  1754.     mov    al, int_no        ; Get board's interrupt vector
  1755.     add    al, 8
  1756.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  1757.     jb    set_int_num        ; No.
  1758.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  1759. set_int_num:
  1760.     xor    ah, ah            ; Clear high byte
  1761.     mov    int_num, ax        ; Set parameter_list int num.
  1762.  
  1763.     clc                ;indicate no errors.
  1764.     ret
  1765.  
  1766.     public    print_parameters
  1767. print_parameters:
  1768. ;echo our command-line parameters
  1769.     cmp    class_name_ptr,0
  1770.     je    echo_args_1
  1771.  
  1772.     mov    dx,offset class_name
  1773.     mov    ah,9
  1774.     int    21h
  1775.     mov    dx,class_name_ptr
  1776.     mov    ah,9
  1777.     int    21h
  1778.     jmp    short echo_args_2
  1779. echo_args_1:
  1780.     mov    di,offset driver_class
  1781.     mov    dx,offset class_name
  1782.     call    print_number
  1783. echo_args_2:
  1784.  
  1785.     mov    di,offset int_no
  1786.     mov    dx,offset int_no_name
  1787.     call    print_number
  1788.     mov    di,offset io_addr
  1789.     mov    dx,offset io_addr_name
  1790.     call    print_number
  1791.  
  1792.     cmp    io_addr,03f8h        ;is this com1?
  1793.     jne    ia_com2
  1794.     mov    dx,offset unusual_com1
  1795.     cmp    int_no,4        ;com1 usually uses IRQ 4.
  1796.     jne    ia_unusual
  1797.     jmp    short ia_usual
  1798. ia_com2:
  1799.     cmp    io_addr,02f8h        ;is this com2?
  1800.     jne    ia_usual        ;no.
  1801.     mov    dx,offset unusual_com2
  1802.     cmp    int_no,3        ;com2 usually uses IRQ 3.
  1803.     je    ia_usual
  1804. ia_unusual:
  1805.     mov    ah,9
  1806.     int    21h
  1807. ia_usual:
  1808.     mov    di,offset baud_rate
  1809.     mov    dx,offset baud_rate_name
  1810.     call    print_number
  1811.     mov    di,offset recv_buf_size
  1812.     mov    dx,offset recv_buf_name
  1813.     call    print_number
  1814.     ret
  1815. code    ends
  1816.     end
  1817.  
  1818.